package com.freewater.javabase.demo.network.auth;

import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.net.Authenticator;
import java.net.PasswordAuthentication;

public class DialogAuthenticator extends Authenticator {

    private JDialog passwordDialog;
    private JTextField userNameField = new JTextField(20);
    private JPasswordField passwordField = new JPasswordField(20);
    private JButton okButton = new JButton("OK");
    private JButton cancelButton = new JButton("Cancel");
    private JLabel mainLabel = new JLabel("Please enter username and password");
    private PasswordAuthentication response = null;

    public DialogAuthenticator() {
        this("", new JFrame());
    }

    public DialogAuthenticator(String username) {
        this(username, new JFrame());
    }

    public DialogAuthenticator(JFrame parent) {
        this("", parent);
    }

    public DialogAuthenticator(String username, JFrame parent) {
        this.passwordDialog = new JDialog(parent, true);
        Container pane = passwordDialog.getContentPane();
        pane.setLayout(new GridLayout(4, 1));
        pane.add(mainLabel);
        //
        JLabel userLabel = new JLabel("Username: ");
        JLabel passwordLabel = new JLabel("Password: ");
        JPanel p2 = new JPanel();
        p2.add(userLabel);
        p2.add(userNameField);
        userNameField.setText(username);
        pane.add(p2);
        //
        JPanel p3 = new JPanel();
        p3.add(passwordLabel);
        p3.add(passwordField);
        pane.add(p3);
        //
        JPanel p4 = new JPanel();
        p4.add(okButton);
        p4.add(cancelButton);
        pane.add(p4);
        passwordDialog.pack();
        //
        ActionListener a1 = new OKResponse();
        okButton.addActionListener(a1);
        userNameField.addActionListener(a1);
        passwordField.addActionListener(a1);
        cancelButton.addActionListener(new CancelResponse());
    }

    private void show() {
        String prompt = this.getRequestingPrompt();
        if (prompt != null) {
            String site = this.getRequestingSite().getHostName();
            String protocol = this.getRequestingProtocol();
            int port = this.getRequestingPort();
            if (site != null & protocol != null) {
                prompt = protocol + "://" + site;
                if (port > 0) {
                    prompt += ":" + port;
                }
            }
            mainLabel.setText("Please enter username and password for " + prompt);
            passwordDialog.pack();
            passwordDialog.setVisible(true);
        }
    }

    @Override
    protected PasswordAuthentication getPasswordAuthentication() {
        final String scheme = this.getRequestingScheme();
        if ("basic".equalsIgnoreCase(scheme)) {
            this.show();
            if (this.response != null) {
                System.out.println(String.format("received username: %s, password: %s",
                        this.response.getUserName(), new String(this.response.getPassword())));
            } else {
                System.out.println("received auth info is null");
            }
            return this.response;
        } else {
            // 如果不希望对这个请求完成认证，则返回null，Java会会告诉服务器它不知道如何认证这个链接；
            return null;
        }
    }

    class OKResponse implements ActionListener {

        @Override
        public void actionPerformed(ActionEvent e) {
            // 处于安全考虑，密码作为char数组返回
            final String username = userNameField.getText();
            final char[] password = passwordField.getPassword();
            // 清除口令，以防再次使用
            passwordField.setText("");
            response = new PasswordAuthentication(username, password);
            passwordDialog.setVisible(false);
        }
    }

    class CancelResponse implements ActionListener {

        @Override
        public void actionPerformed(ActionEvent e) {
            // 清除口令，以防再次使用
            passwordField.setText("");
            passwordDialog.setVisible(false);
            response = null;
        }
    }
}
